package com.sunday.boot3.user.center.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sunday.boot3.user.center.pojo.dto.permissions.*;
import com.sunday.boot3.user.center.repository.dao.PermissionsDao;
import com.sunday.boot3.user.center.repository.entity.Permissions;
import com.sunday.boot3.user.center.service.PermissionsService;
import com.sunday.common.core.asserts.BusinessAssert;
import com.sunday.common.core.converter.MapperConvert;
import com.sunday.common.core.enums.ErrorCodeEnum;
import com.sunday.common.core.permissions.PermissionsEncode;
import com.sunday.common.core.remoting.base.page.PageResultDTO;
import com.sunday.common.leaf.core.IdWorker;
import com.sunday.common.mybatis.plus.query.PageWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Description: 权限表 服务实现类
 * @author: zsy
 * @Create: 2024/09/22 16:24:38
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PermissionsServiceImpl implements PermissionsService {

    private final PermissionsDao permissionsDao;

    /**
     * @Description: 新增 权限表 数据
     * @Param: [savePermissionsReqDTO]
     * @Return: void
     * @Author: zsy
     * @Time: 2024/09/22 16:24:38
     */
    @Override
    public void save(SavePermissionsReqDTO savePermissionsReqDTO) {
        /**
         * 唯一性判定
         */
        LambdaQueryWrapper<Permissions> permissionQW = Wrappers.lambdaQuery();
        permissionQW
                .select(Permissions::getId)
                .eq(Permissions::getUrl, savePermissionsReqDTO.getUrl())
                .last("limit 1");
        BusinessAssert.isTrue(permissionsDao.getOne(permissionQW) == null, ErrorCodeEnum.A0_506, () -> "权限Url重复");

        /**
         * 获取最高位权限位和权限码
         */
        PermissionsEncode.Result result = getMaxBitCode();
        Permissions permissions = MapperConvert.map(savePermissionsReqDTO, Permissions.class);
        permissions.setId(IdWorker.getId());
        permissions.setPosition(result.getPosition());
        permissions.setCode(result.getCode());
        permissions.setCreateTime(LocalDateTime.now());
        BusinessAssert.isTrue(permissionsDao.save(permissions), ErrorCodeEnum.A0_440);
    }

    /**
     * @Description: 获取最高位权限位和权限码
     * @Param: []
     * @Return: com.ae.user.center.repository.entity.Permission
     * @Author: zsy
     * @Time: 2023/9/5 10:13
     */
    protected PermissionsEncode.Result getMaxBitCode() {
        LambdaQueryWrapper<Permissions> permissionQW = Wrappers.lambdaQuery();
        permissionQW
                .orderByDesc(Permissions::getPosition)
                .orderByDesc(Permissions::getCode)
                .select(Permissions::getPosition, Permissions::getCode)
                .last("limit 1");
        Permissions maxBitCode = permissionsDao.getOne(permissionQW);
        PermissionsEncode.Result result = Optional.ofNullable(maxBitCode)
                .map(max -> PermissionsEncode.next(max.getPosition(), max.getCode()))
                .orElseGet(() -> PermissionsEncode.next(-1, -1L));
        return result;
    }

    /**
     * 权限表 批量权限保存
     *
     * @param saveBatchPermissionsReqDTO
     * @return
     */
    @Override
    public void saveBatch(SaveBatchPermissionsReqDTO saveBatchPermissionsReqDTO) {

        /**
         * 唯一性判定
         */
        List<String> urlList = saveBatchPermissionsReqDTO.getPermissionsReqDTOS().stream()
                .map(permissions -> permissions.getUrl())
                .collect(Collectors.toList());

        LambdaQueryWrapper<Permissions> permissionQW = Wrappers.lambdaQuery();
        permissionQW.in(Permissions::getUrl, urlList);

        BusinessAssert.isTrue(permissionsDao.count(permissionQW) == 0, ErrorCodeEnum.A0_506, () -> "权限Url重复");


        /**
         * 获取最高位权限位和权限码
         */
        PermissionsEncode.Result result = getMaxBitCode();
        log.info("获取最大权限位和权限码 : {}", result);

        List<Permissions> permissionsList = new ArrayList<>();
        for (SavePermissionsReqDTO savePermissionsReqDTO : saveBatchPermissionsReqDTO.getPermissionsReqDTOS()) {
            Permissions permissions = MapperConvert.map(savePermissionsReqDTO, Permissions.class);
            permissions.setId(IdWorker.getId());
            permissions.setPosition(result.getPosition());
            permissions.setCode(result.getCode());
            permissions.setCreateTime(LocalDateTime.now());
            permissionsList.add(permissions);
            // 为下一轮申请position和code
            result = PermissionsEncode.next(result.getPosition(), result.getCode());
        }
        BusinessAssert.isTrue(permissionsDao.saveBatch(permissionsList), ErrorCodeEnum.A0_440);
    }

    /**
     * @Description: 删除 权限表 数据
     * @Param: [removePermissionsReqDTO]
     * @Return: void
     * @Author: zsy
     * @Time: 2024/09/22 16:24:38
     */
    @Override
    public void remove(RemovePermissionsReqDTO removePermissionsReqDTO) {
        BusinessAssert.isTrue(permissionsDao.removeByIds(removePermissionsReqDTO.getIds()), ErrorCodeEnum.A0_440);
    }

    /**
     * @Description: 修改 权限表 数据
     * @Param: [updatePermissionsReqDTO]
     * @Return: void
     * @Author: zsy
     * @Time: 2024/09/22 16:24:38
     */
    @Override
    public void update(UpdatePermissionsReqDTO updatePermissionsReqDTO) {
        LambdaUpdateWrapper<Permissions> permissionsUW = Wrappers.lambdaUpdate();
        permissionsUW.eq(Permissions::getId, updatePermissionsReqDTO.getId());
        permissionsUW.set(Permissions::getName, updatePermissionsReqDTO.getName())
                .set(Permissions::getCategory, updatePermissionsReqDTO.getCategory())
                .set(Permissions::getUrl, updatePermissionsReqDTO.getUrl())
                .set(Permissions::getPosition, updatePermissionsReqDTO.getPosition())
                .set(Permissions::getCode, updatePermissionsReqDTO.getCode())
                .set(Permissions::getParentId, updatePermissionsReqDTO.getParentId());
        BusinessAssert.isTrue(permissionsDao.update(permissionsUW), ErrorCodeEnum.A0_440);
    }

    /**
     * @Description: 获取 权限表 分页列表数据
     * @Param: [pagePermissionsReqDTO]
     * @Return: com.sunday.common.core.remoting.base.page.PageResultDTO<com.sunday.boot3.user.center.pojo.dto.permissions.PagePermissionsResDTO>
     * @Author: zsy
     * @Time: 2024/09/22 16:24:38
     */
    @Override
    public PageResultDTO<PagePermissionsResDTO> page(PagePermissionsReqDTO pagePermissionsReqDTO) {
        LambdaQueryWrapper<Permissions> permissionsQW = Wrappers.lambdaQuery();
        permissionsQW.eq(ObjectUtils.isNotEmpty(pagePermissionsReqDTO.getId()), Permissions::getId, pagePermissionsReqDTO.getId())
                .eq(StringUtils.isNotBlank(pagePermissionsReqDTO.getName()), Permissions::getName, pagePermissionsReqDTO.getName())
                .eq(ObjectUtils.isNotEmpty(pagePermissionsReqDTO.getCategory()), Permissions::getCategory, pagePermissionsReqDTO.getCategory())
                .eq(StringUtils.isNotBlank(pagePermissionsReqDTO.getUrl()), Permissions::getUrl, pagePermissionsReqDTO.getUrl())
                .eq(ObjectUtils.isNotEmpty(pagePermissionsReqDTO.getPosition()), Permissions::getPosition, pagePermissionsReqDTO.getPosition())
                .eq(ObjectUtils.isNotEmpty(pagePermissionsReqDTO.getCode()), Permissions::getCode, pagePermissionsReqDTO.getCode())
                .eq(ObjectUtils.isNotEmpty(pagePermissionsReqDTO.getParentId()), Permissions::getParentId, pagePermissionsReqDTO.getParentId())
                .eq(ObjectUtils.isNotEmpty(pagePermissionsReqDTO.getCreateTime()), Permissions::getCreateTime, pagePermissionsReqDTO.getCreateTime());
        return PageWrapper.result(permissionsDao.page(PageWrapper.map(pagePermissionsReqDTO, Permissions::getId), permissionsQW), data -> MapperConvert.map(data, PagePermissionsResDTO.class));
    }

    /**
     * 全量获取 权限标数据
     *
     * @param
     * @return {@link Collection< ListPermissionsResDTO>}
     */
    @Override
    public Collection<ListPermissionsResDTO> list() {
        return MapperConvert.batchMap(permissionsDao.list(), ListPermissionsResDTO.class);
    }

}
